AWS IAMロールAnywhereのPKI基盤にHashicorp Vaultを使う
ども、ゲストのNTT東日本 大瀧です。
本日IAMロールAnywhereがリリースされました。IAMロールAnywhereは、AWSの認証基盤であるIAMの認証をPKI(公開鍵基盤)に外出しできる仕組みです。本ブログでは、手軽に試せるPKIとしてHashicorp Vaultを試す様子をご紹介します。
- 動作確認環境
- OS : Ubuntu 20.04.4 LTS
- Vault : バージョン v1.11.0
- AWS : 東京リージョン
1. Hashicorp Vaultのセットアップ
まずはPKIのCA(認証局)となるVaultサーバーを立ち上げます。Vaultのダウンロードページの [Linux] - [LINUX BINARY DOWNLOAD]で Amd64
のリンクをコピーし、 wget
の引数にしてダウンロードします。
$ wget https://releases.hashicorp.com/vault/1.11.0/vault_1.11.0_linux_amd64.zip --2022-07-07 21:09:51-- https://releases.hashicorp.com/vault/1.11.0/vault_1.11.0_linux_amd64.zip :(略) vault_1.11.0_linux_amd64.zip 100%[=================================================>] 70.07M 24.6MB/s in 2.9s 2022-07-07 21:09:54 (24.6 MB/s) - ‘vault_1.11.0_linux_amd64.zip’ saved [73474942/73474942] $ unzip vault_1.11.0_linux_amd64.zip Archive: vault_1.11.0_linux_amd64.zip inflating: vault $
以下のように実行し、ヘルプメッセージが出ればOKです。
$ ./vault Usage: vault <command> [args] Common commands: read Read data and retrieves secrets write Write data, configuration, and secrets delete Delete secrets and configuration list List data or secrets login Authenticate locally agent Start a Vault agent server Start a Vault server status Print seal and HA status unwrap Unwrap a wrapped secret :(略) $
今回はお試しなので、Devモードでサーバーをバックグラウンド起動しておきます。
$ ./vault server -dev & ==> Vault server configuration: Api Address: http://127.0.0.1:8200 Cgo: disabled Cluster Address: https://127.0.0.1:8201 Go Version: go1.17.11 Listener 1: tcp (addr: "127.0.0.1:8200", cluster address: "127.0.0.1:8201", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled") Log Level: info Mlock: supported: true, enabled: false Recovery Mode: false Storage: inmem Version: Vault v1.11.0, built 2022-06-17T15:48:44Z Version Sha: ea296ccf58507b25051bc0597379c467046eb2f1 ==> Vault server started! Log data will stream in below: :(略)
続いてドキュメントに従い、PKIをセットアップします。
以下の6つのコマンドを順に実行していきます。4番目のコマンドでCA証明書が表示されるので、-----BEGIN CERTIFICATE-----
から-----END CERTIFICATE-----
までをコピーして控えておきます(2つ表示されますが自己署名証明書のため中身は同じでどちらでもOKです)。あとのトラストアンカー設定に利用します。
$ export VAULT_ADDR='http://127.0.0.1:8200' $ ./vault secrets enable pki 2022-07-07T18:03:43.478+0900 [INFO] core: successful mount: namespace="" path=pki/ type=pki Success! Enabled the pki secrets engine at: pki/ $ ./vault secrets tune -max-lease-ttl=8760h pki 2022-07-07T18:03:50.060+0900 [INFO] core: mount tuning of leases successful: path=pki/ Success! Tuned the secrets engine at: pki/ $ ./vault write pki/root/generate/internal \ common_name=my-website.com \ ttl=8760h WARNING! The following warnings were returned from Vault: * This mount hasn't configured any authority access information fields; this may make it harder for systems to find missing certificates in the chain or to validate revocation status of certificates. Consider updating /config/urls with this information. Key Value --- ----- certificate -----BEGIN CERTIFICATE----- MIIDPjCCAiagAwIBAgIUCyC8uqaeOkgcbvciBnJHUKFY/rAwDQYJKoZIhvcNAQEL :(略) kWBT7k944hCusBIGiy4LELneaJuDDG+ea/Aq2XB+ePhiIUgYh4IDagj05SSCCWh9 e0HfxqSfSYknFqpGw/SAhjfo -----END CERTIFICATE----- expiration 1688720638 issuer_id 3e02420a-d003-ee56-d566-72ef7c3cc8f0 issuer_name n/a issuing_ca -----BEGIN CERTIFICATE----- MIIDPjCCAiagAwIBAgIUCyC8uqaeOkgcbvciBnJHUKFY/rAwDQYJKoZIhvcNAQEL :(略) kWBT7k944hCusBIGiy4LELneaJuDDG+ea/Aq2XB+ePhiIUgYh4IDagj05SSCCWh9 e0HfxqSfSYknFqpGw/SAhjfo -----END CERTIFICATE----- key_id 002874cf-7dd7-cb56-ea5e-d0d760037adf key_name n/a serial_number 0b:20:bc:ba:a6:9e:3a:48:1c:6e:f7:22:06:72:47:50:a1:58:fe:b0 $ ./vault write pki/config/urls \ issuing_certificates="http://127.0.0.1:8200/v1/pki/ca" \ crl_distribution_points="http://127.0.0.1:8200/v1/pki/crl" Success! Data written to: pki/config/urls $ ./vault write pki/roles/example-dot-com \ allowed_domains=my-website.com \ allow_subdomains=true \ max_ttl=72h Success! Data written to: pki/roles/example-dot-com
これでOKです。
2. IAMロールAnywhereのセットアップ
Management ConsoleのIAMロールAnywhere画面にアクセスし、[信頼アンカーを作成する]ボタンをクリックします。
IAM管理画面はリージョンに依存しないグローバル扱いですが、IAMロールAnywhereはリージョンごとの設定のためリージョンを選択することに注意します。
[信頼アンカー名]は任意の名前を入力、[認証機関(CA)ソース]は「外部証明書バンドル」を選択し、[外部証明書バンドル]に手順1で控えておいたCA証明書をペーストします。他の項目は未選択にし、[信頼アンカーを作成する]ボタンをクリックし登録します。
続いて、IAM管理画面から任意のロールを新規作成します。今回はマネージドポリシーAmazonS3ReadOnlyAccess
を持つIAMRoleAnywhereEvalRole
ロールを作成しました。作成したロールの[信頼関係]タブをクリック、[信頼関係を編集]ボタンをクリックして以下のJSONを貼り付け[ポリシーを更新]ボタンで保存します。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": [ "rolesanywhere.amazonaws.com" ] }, "Action": [ "sts:AssumeRole", "sts:TagSession", "sts:SetSourceIdentity" ] } ] }
IAMロールAnywhereの画面に戻り、プロファイル一覧の右にある[プロファイルを作成]ボタンをクリックします。
プロファイル作成画面では、任意のプロファイル名とロールに先ほど作成したIAMロールを指定、他の項目は既定のまま[プロファイルを作成]をクリックします。
これでOKです。
動作確認
では、動かしてみましょう。まずはVaultで証明書を発行します。
$ ./vault write pki/issue/example-dot-com \ common_name=www.my-website.com Key Value --- ----- ca_chain [-----BEGIN CERTIFICATE----- MIIDPjCCAiagAwIBAgIUCyC8uqaeOkgcbvciBnJHUKFY/rAwDQYJKoZIhvcNAQEL :(略) -----END CERTIFICATE-----] certificate -----BEGIN CERTIFICATE----- MIIDxzCCAq+gAwIBAgIUQkSqI2Gb59LiQw8hw/O/YGQfuR4wDQYJKoZIhvcNAQEL :(略) -----END CERTIFICATE----- expiration 1657443883 issuing_ca -----BEGIN CERTIFICATE----- MIIDPjCCAiagAwIBAgIUCyC8uqaeOkgcbvciBnJHUKFY/rAwDQYJKoZIhvcNAQEL :(略) -----END CERTIFICATE----- private_key -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAvs5mGTllc45uRurm69V/w/LxElhh0w45blPi/ROnjZ5IgII1 :(略) -----END RSA PRIVATE KEY----- private_key_type rsa serial_number 42:44:aa:23:61:9b:e7:d2:e2:43:0f:21:c3:f3:bf:60:64:1f:b9:1e
いくつか出てくる項目のうち、以下をそれぞれテキストファイルに保存します。
- certファイル :
certificate
の-----BEGIN CERTIFICATE-----
~-----END CERTIFICATE-----
まで - keyファイル :
private_key
の-----BEGIN RSA PRIVATE KEY-----
~-----END RSA PRIVATE KEY-----
まで
続いてIAMロールAnywhereを利用するヘルパースクリプトをドキュメントにあるリンクから環境にあったリンクをコピーし、wget
コマンドでダウンロードします。
$ wget https://s3.amazonaws.com/roles-anywhere-credential-helper/CredentialHelper/latest/linux_amd64/aws_signing_helper :(略) $ chmod +x aws_signing_helper
これで準備OKです。IAMロールAnywhereのAPIをコールし、一時クレデンシャルを取得してみましょう。AWS管理コンソールから、以下のコマンドラインに対応する各項目のARNをコピーし、コマンドラインを完成させ実行します。
$ ./aws_signing_helper credential-process --certificate ./cert --private-key ./key \ --trust-anchor-arn <IAMロールAnywhere トラストアンカーのARN> \ --profile-arn <IAMロールAnywhere プロファイルのARN> \ --role-arn <手順2で作成したIAMロールのARN> {"Version":1,"AccessKeyId":"ASIAXXXXXXXXXXXX","SecretAccessKey":"XXXXXXXXXXXXXXXXXXXXXXXX","SessionToken":"XXXXXXXXXXXXXXXXXXXXXXXX","Expiration":"2022-07-07T11:02:01Z"}
正常に実行できると、JSON形式のレスポンスに一時クレデンシャルの情報が含まれている様子がわかります。AWS CLIで利用する場合は、上記コマンドを ~/.aws/config
ファイル内に以下の形式で記載します。(プロファイル名は好きなものでOKです)
[profile developer] credential_process = ./aws_signing_helper credential-process --certificate ./cert --private-key ./key --trust-anchor-arn <IAMロールAnywhere トラストアンカーのARN> --profile-arn <IAMロールAnywhere プロファイルのARN> --role-arn <手順2で作成したIAMロールのARN>
これを設定すると、本来APIキーなどを設定する ~/.aws/credentials
ファイルが空でも...
$ aws s3 ls --profile developer 2022-05-18 15:57:09 takipone-lambda-layers 2022-03-04 14:56:12 takipone-transcribe $
クレデンシャルなしで、証明書から一時クレデンシャルを取得しAWS APIを呼ぶことができました!
まとめ
IAMロールAnywhereのPKI基盤としてHashicorp Vaultを試してみる様子をご紹介しました。
リリース文だけ見るとPKIで発行した証明書がどうIAMと連携するのかイメージしずらいと思うので、こうやってまずは試してみてできること、そうでないことを検証してみるのがオススメです。
私見として、以下をメモしておきます。
- x.509証明書で認証といっても、mTLSのようなクライアント証明書として使うものではない。証明書をIAMロールAnywhereに提示して一時クレデンシャルを取得するものなので、AWS SDKやAWS CLIなどAWS APIに準拠するクライアントで利用するもの。
- といっても現状ヘルパースクリプトを噛ませる形なので、コンテナ環境などファイルを扱いにくい環境では使いずらい印象。AWS SDKの各言語でネイティブに対応してくれるのを待つのがいいかしら。
- 証明書の漏洩に備えるCRLは、IAMロールAnywhere APIのImportCrlで扱える。Vault EnterpriseあたりでSync機能が出てきたりすると便利そう。